﻿using System;
using System.Collections.Generic;


namespace epicenter2010.Domain.Entity
{
	/// <summary>
	/// bstack @ 05/06/2010
	/// Order entity, state changeable - behavioural
	/// </summary>
	public class Order : epicenter2010.Common.EntityBase<int>
	{
		private IDictionary<int, epicenter2010.Domain.Entity.OrderItem> c_items;


		/// <summary>
		/// Customer Id
		/// </summary>
		public readonly int CustomerId;

		/// <summary>
		/// Description
		/// </summary>
		public readonly string Description;

		/// <summary>
		/// Status
		/// </summary>
		public epicenter2010.Domain.Entity.OrderStatus Status { get; private set; }

		/// <summary>
		/// Items
		/// </summary>
		public IEnumerable<epicenter2010.Domain.Entity.OrderItem> Items { get { return this.c_items.Values; } }


		/// <summary>
		/// Ctor
		/// </summary>
		/// <param name="Id"></param>
		/// <param name="customerId"></param>
		/// <param name="description"></param>
		public Order(
			int Id,
			int customerId,
			string description) : base(Id, DateTimeOffset.UtcNow)
		{
			epicenter2010.Common.DBCChecker.RequireArgument("customerId", customerId > 0, "Invalid argument");
			epicenter2010.Common.DBCChecker.RequireArgumentNotEmpty("description", description);
			
			this.CustomerId = customerId;
			this.Description = description;
		}


		/// <summary>
		/// Initiate order
		/// </summary>
		public void Initiate()
		{
			// Invariant check
			epicenter2010.Common.DBCChecker.Invariant(this.Status == epicenter2010.Domain.Entity.OrderStatus.None,
				"Invalid entity state exception");

			// Other logic may exist here

			this.Status = epicenter2010.Domain.Entity.OrderStatus.Initiated;
		}

		/// <summary>
		/// Initiate order
		/// </summary>
		public void TransitionToInProcess()
		{
			epicenter2010.Common.DBCChecker.Require(this.Status == epicenter2010.Domain.Entity.OrderStatus.Initiated,
				"Invalid entity state exception");
			epicenter2010.Common.DBCChecker.Require(this.c_items != null && this.c_items.Count > 0, 
				"Cannot initiate order unless at least one order item exists");

			// Other logic may exist here

			this.Status = epicenter2010.Domain.Entity.OrderStatus.Initiated;
		}


		/// <summary>
		/// Add order item
		/// </summary>
		/// <param name="subject"></param>
		public void AddOrderItem(epicenter2010.Domain.Entity.OrderItem subject)
		{
			epicenter2010.Common.DBCChecker.RequireArgumentNotNull("subject", subject);

			if (this.c_items == null) this.c_items = new Dictionary<int, epicenter2010.Domain.Entity.OrderItem>();

			this.c_items.Add(subject.Id, subject);
		}


		// TODO: BS 06/06/2010 Other methods would exist here ...
	}
}